﻿using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using My.Admin.Dto.System;
using My.Admin.Enum;
using My.Admin.Model.System;
using My.Admin.Service.System.IService;
using My.Core.CustomException;
using My.Core.Enums;
using System.ComponentModel;

namespace My.Admin.Service.System
{
	public class SysMenuService : BaseService<SysMenu>, ISysMenuService
	{
		private readonly ISysUserRoleService _sysUserRoleService;
		private readonly ISysRoleMenuService _sysRoleMenuService;
		private readonly UserManager _userManager;

		public SysMenuService(UserManager userManager, ISysRoleMenuService sysRoleMenuService, ISysUserRoleService sysUserRoleService)
		{
			_userManager = userManager;
			_sysUserRoleService = sysUserRoleService;
			_sysRoleMenuService = sysRoleMenuService;
		}
		/// <summary>
		/// 获取登录菜单树
		/// </summary>
		/// <returns></returns>
		public async Task<List<MenuOutput>> QuerySysMenu()
		{
			var menuList = await AsQueryable()
				.Where(u => u.Type != MenuTypeEnum.Btn && u.Status == StatusEnum.Enable)
				.OrderBy(u => new { u.OrderNo, u.Id }).ToTreeAsync(u => u.Children, u => u.Pid, 0);
			return menuList.Adapt<List<MenuOutput>>();
		}

		/// <summary>
		/// 获取菜单列表
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public async Task<List<SysMenu>> GetList(MenuInput input)
		{
			var menuIdList = new List<long>();

			// 有筛选条件时返回list列表（防止构造不出树）
			if (!string.IsNullOrWhiteSpace(input.Title) || input.Type is > 0)
			{
				return await AsQueryable()
					.WhereIF(!string.IsNullOrWhiteSpace(input.Title), u => u.Title.Contains(input.Title))
					.WhereIF(input.Type is > 0, u => u.Type == input.Type)
					.WhereIF(menuIdList.Count > 1, u => menuIdList.Contains(u.Id))
					.OrderBy(u => u.OrderNo).ToListAsync();
			}

			return await AsQueryable().OrderBy(u => u.OrderNo).ToTreeAsync(u => u.Children, u => u.Pid, 0); // 角色菜单授权时
		}

		/// <summary>
		/// 增加菜单
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public async Task AddMenu(AddMenuInput input)
		{
			var isExist = input.Type != MenuTypeEnum.Btn
				? await IsAnyAsync(u => u.Title == input.Title)
				: await IsAnyAsync(u => u.Permission == input.Permission);

			if (isExist)
				throw new CustomException(ResultCode.CUSTOM_ERROR, "菜单已存在", "菜单已存在");
			// 校验菜单参数
			var sysMenu = input.Adapt<SysMenu>();
			CheckMenuParam(sysMenu);

			await InsertAsync(sysMenu);
		}

		/// <summary>
		/// 更新菜单
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public async Task UpdateMenu(UpdateMenuInput input)
		{
			if (input.Id == input.Pid)
				throw new CustomException(ResultCode.CUSTOM_ERROR, "禁止本节点与父节点相同", "禁止本节点与父节点相同");

			var isExist = input.Type != MenuTypeEnum.Btn
				? await IsAnyAsync(u => u.Title == input.Title && u.Type == input.Type && u.Id != input.Id)
				: await IsAnyAsync(u => u.Permission == input.Permission && u.Type == input.Type && u.Id != input.Id);
			if (isExist)
				throw new CustomException(ResultCode.CUSTOM_ERROR, "菜单已存在", "菜单已存在");

			// 校验菜单参数
			var sysMenu = input.Adapt<SysMenu>();
			CheckMenuParam(sysMenu);

			await AsUpdateable(sysMenu).ExecuteCommandAsync();
			;
		}

		/// <summary>
		/// 删除菜单
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public async Task DeleteMenu(DeleteMenuInput input)
		{
			var menuTreeList = await AsQueryable().ToChildListAsync(u => u.Pid, input.Id, true);
			var menuIdList = menuTreeList.Select(u => u.Id).ToList();

			await DeleteAsync(u => menuIdList.Contains(u.Id));

			// 级联删除角色菜单数据
			await _sysRoleMenuService.DeleteRoleMenuByMenuIdList(menuIdList);
		}

		/// <summary>
		/// 增加和编辑时检查菜单数据
		/// </summary>
		/// <param name="menu"></param>
		private static void CheckMenuParam(SysMenu menu)
		{
			var permission = menu.Permission;
			if (menu.Type == MenuTypeEnum.Btn)
			{
				menu.Name = null;
				menu.Path = null;
				menu.Component = null;
				menu.Icon = null;
				menu.Redirect = null;
				menu.OutLink = null;
				menu.IsHide = false;
				menu.IsKeepAlive = true;
				menu.IsAffix = false;
				menu.IsIframe = false;

				if (string.IsNullOrEmpty(permission))
					throw new CustomException(ResultCode.CUSTOM_ERROR, "权限标识格式为空", "权限标识格式为空");
				if (!permission.Contains(':'))
					throw new CustomException(ResultCode.CUSTOM_ERROR, "权限标识格式错误 如xxx:xxx", "权限标识格式错误 如xxx:xxx");
			}
			else
			{
				menu.Permission = null;
			}
		}

		/// <summary>
		/// 获取用户拥有按钮权限集合
		/// </summary>
		/// <returns></returns>
		public async Task<List<string>> GetOwnBtnPermList()
		{
			var userId = _userManager.UserId;
			var menuIdList = _userManager.SuperAdmin ? new List<long>() : await GetMenuIdList();
			var permissions = await AsQueryable()
				.Where(u => u.Type == MenuTypeEnum.Btn)
				.WhereIF(menuIdList.Count > 0, u => menuIdList.Contains(u.Id))
				.Select(u => u.Permission).ToListAsync();
			return permissions;
		}

		/// <summary>
		/// 获取系统所有按钮权限集合
		/// </summary>
		/// <returns></returns>
		public async Task<List<string>> GetAllBtnPermList()
		{
			var permissions = await AsQueryable()
					.Where(u => u.Type == MenuTypeEnum.Btn)
					.Select(u => u.Permission).ToListAsync();
			return permissions;
		}

		/// <summary>
		/// 获取当前用户菜单Id集合
		/// </summary>
		/// <returns></returns>
		private async Task<List<long>> GetMenuIdList()
		{
			var roleIdList = await _sysUserRoleService.GetUserRoleIdList(_userManager.UserId);
			return await _sysRoleMenuService.GetRoleMenuIdList(roleIdList);
		}
	}
}
